package com.zhdl.modules.slagRemoval.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.project.common.util.DelayUtil;
import com.zhdl.common.util.WebResult;
import com.zhdl.hardware.io.smartLink.repository.impl.IOCmdHandleDaoImpl;
import com.zhdl.hardware.io.smartLink.service.IOCmdSendService;
import com.zhdl.hardware.io_socket.response.IOSseEmitterVO;
import com.zhdl.hardware.io_socket.service.IOWebsocketService;
import com.zhdl.hardware.motor.huichuan.repository.HcPortCmdHandleDao;
import com.zhdl.hardware.motor.huichuan.repository.impl.HcPortCmdHandle;
import com.zhdl.modules.slagRemoval.SlagRemovalProcess;
import com.zhdl.modules.slagRemoval.service.SlagRemovalService;
import com.zhdl.modules.tools.CommonCallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static com.zhdl.modules.slagRemoval.SlagRemovalProcess.isRunning;
import static com.zhdl.modules.slagRemoval.SlagRemovalProcess.mode;

@Slf4j
@RestController
@RequestMapping(path = "/slagRemoval", produces = MediaType.APPLICATION_JSON_VALUE)

public class SlagRemovalController {

    private static final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    private final Map<Integer, SseEmitter> sseEmitters = new ConcurrentHashMap<>();
    @Resource
    private IOCmdHandleDaoImpl ioHandleDao;
    @Resource
    private HcPortCmdHandle hcPortCmdHandle;
    @Resource
    private IOWebsocketService ioWebsocketService;
    private long sseSeq;

    @Resource
    private IOCmdSendService ioCmdSendService;
    @Resource
    private HcPortCmdHandleDao hcPortCmdHandleDao;
    @Resource
    private SlagRemovalProcess slagRemovalProcess;
    @Resource
    private SlagRemovalService slagRemovalService;

    /**
     * 首页数据请求
     */
    @GetMapping(value = "/sse/{id}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter handleSse(@PathVariable Integer id) {
        SseEmitter emitter = new SseEmitter();
        sseEmitters.put(id, emitter);
        // 超时移除
        emitter.onTimeout(() -> {
            emitter.complete();
            sseEmitters.remove(id);
        });
        // 完成移除
        emitter.onCompletion(() -> sseEmitters.remove(id));
        // 每一秒发送一条消息
        executorService.scheduleAtFixedRate(() -> {

            ObjectMapper mapper = new ObjectMapper();

            //加载内存数据
            WebResult<IOSseEmitterVO> sseResp = WebResult.okResult(ioWebsocketService.getIoSseEmitterVO());
            try {
                emitter.send(SseEmitter.event().
                        id(String.valueOf(getSseSeq())).
                        data(mapper.writeValueAsString(sseResp),
                                MediaType.APPLICATION_JSON));
                log.info("send" + sseResp);
            } catch (IOException e) {
                emitter.complete();
            }
        }, 0, 1, TimeUnit.SECONDS);

        return emitter;
    }

    /**
     * 获取SSE序号
     */
    private long getSseSeq() {
        if (sseSeq > 65535L * 65535)
            sseSeq = 0;
        return sseSeq++;
    }

    @GetMapping("/init")
    public WebResult<String> ioInit() {
        ioHandleDao.init("192.168.1.108:502");
        hcPortCmdHandle.addPort("7");
        hcPortCmdHandle.addPort("8");
        log.info("ioHandleDao" + ",hcCmdHandleDao init");
        return WebResult.okResult("IO INIT!");
    }

    /**
     * 电机回原点前 夹爪松开
     *
     * @param model 0 / 1
     * @return
     */
    @GetMapping("/backOriginPick")
    public WebResult<String> backOriginPick(int model) {
        slagRemovalService.manualBackOriginPickNS(model);
        return WebResult.okResult("Back origin success!");
    }

    /**
     * 电机回原点
     *
     * @param model 0 / 1
     * @return
     */
    @GetMapping("/back")
    public WebResult<String> manualBackOrigin(int model) {
        if (!isRunning) {
            isRunning = true;
            slagRemovalService.manualBackOriginNS(model);
            return WebResult.okResult("Slag Process Start Success!");
        }
        return null;
    }
    /**
     * 电机使能停止
     *
     * @param model 0 / 1
     * @return
     */
    @GetMapping("/stopReady")
    public WebResult<String> stopReady(int model) {
        slagRemovalService.manualStopReadyNS(model);
        DelayUtil.delayedExecution(1000, () -> {
            slagRemovalService.manualStartReadyNS(model);
            log.info("");
        });
        return WebResult.okResult("Motor no ready success!");
    }
    /**
     * 电机使能开始
     *
     * @param model 0 / 1
     * @return
     */
    @GetMapping("/startReady")
    public WebResult<String> startReady(int model) {
        slagRemovalService.manualStartReadyNS(model);
        isRunning = false;
        return WebResult.okResult("Motor all ready success!");
    }

    /**
     * 除渣流程开始
     *
     * @param id 南北运动 0 / 1
     */
    @GetMapping("/slagRunProcess")
    public WebResult<String> slagRunProcess(int id) {
        if (!isRunning) {
            mode = false;
            slagRemovalProcess.processAutomaticMode(id);
            String direction = "";
            if (id == 0){
                direction = "北边";
            } else {
                direction = "南边";
            }
            return WebResult.okResult("Slag Process "+ direction +" Start Success!");
        }
        return null;
    }

    @GetMapping("/down")
    public WebResult<String> manualPutDownCage(int id) {
        if (!isRunning) {
            isRunning = true;
            slagRemovalService.manualPutDownCage(id);
            return WebResult.okResult("Slag Process Start Success!");
        }
        return null;
    }

    @GetMapping("/down1")
    public WebResult<String> manualPutDownCage1(int id) {
        if (!isRunning) {
            isRunning = true;
            slagRemovalService.manualPutDownCage1(id);
            return WebResult.okResult("Slag Process Start Success!");
        }
        return null;
    }

    @GetMapping("/up")
    public WebResult<String> manualLiftCageOne(int id) {
        if (!isRunning) {
            isRunning = true;
            slagRemovalService.manualLiftCageOne(id);
            return WebResult.okResult("Slag Process Start Success!");
        }
        return null;
    }
    @GetMapping("/up1")
    public WebResult<String> manualLiftCageOne1(int id) {
        if (!isRunning) {
            isRunning = true;
            slagRemovalService.manualLiftCageOne1(id);
            return WebResult.okResult("Slag Process Start Success!");
        }
        return null;
    }

    @GetMapping("/manualModeNorthStart")
    public WebResult<String> manualModeNorthStart(int xid, int zid) {
        if (!isRunning) {
            mode = true;
            slagRemovalProcess.processManualNorthMode(xid, zid);
            return WebResult.okResult("Slag Process Start Success!");
        }
        return null;
    }

    @GetMapping("/manualModeSouthStart")
    public WebResult<String> manualModeSouthStart(int xid, int zid) {
        if (!isRunning) {
            mode = true;
            slagRemovalProcess.processManualSouthMode(xid, zid);
            return WebResult.okResult("Slag Process Start Success!");
        }
        return null;
    }

    /*
    除渣X轴运动
 */
    @GetMapping("/slagRunX")
    public WebResult<String> slagRunX(String id, int distance, int speed) {
        String port = getPort(id);
        id = getId(id);
        //开始的时候，先让电机停止使能
        hcPortCmdHandleDao.motorWriteSlagStop(port, id);
        //设置运行需要的速度 -默认 第0到第1端运行
        hcPortCmdHandleDao.setSlagMoveDist(port, id, "110C", distance);
        hcPortCmdHandleDao.writeSlag06(port, id, "110E", speed);
        //运动使能 17
        String finalId = id;
        DelayUtil.delayedExecution(1000, () ->
                hcPortCmdHandleDao.motorWriteSlagRun(port, finalId));
        return WebResult.okResult("X-Motor Run distance is : " + distance + ",speed is : " + speed + "success!");
    }

    public String getPort(String id) {
        if ("1".equals(id) || "2".equals(id) || "5".equals(id)) {
            return "7";
        }
        return "8";
    }

    public String getId(String id) {
        if ("1".equals(id) || "3".equals(id)) {
            return "1";
        }
        if ("2".equals(id) || "4".equals(id)) {
            return "2";
        }
        return "3";
    }

    /*
        除渣X轴停止
     */
    @GetMapping("/slagStopX")
    public WebResult<String> slagStopX(String id) {
        String port = getPort(id);
        id = getId(id);
        //电机停止使能
        hcPortCmdHandleDao.motorWriteSlagStop(port, id);
        return WebResult.okResult("Motor stop run success!");
    }

    /*
        除渣 Z && P轴运动
    */
    @GetMapping("/slagRunZP")
    public WebResult<String> slagRunZP(String id, int ioAddress, int distance, int speed) {

        String port = getPort(id);
        id = getId(id);
        //开始的时候，先让 Z || P 轴 继电器断开 io->01 写入 00
        ioHandleDao.ioWriteCoilSignal(ioAddress, "0000", new CommonCallback<byte[]>() {
            @Override
            public void statusCallback(byte[] bytes) {

            }
        });

        String finalId = id;
        DelayUtil.delayedExecution(500, () -> {
            //其次让电机停止使能 00
            hcPortCmdHandleDao.motorWriteSlagStop(port, finalId);
            //hcPortCmdHandleDao -默认 第0到第1端运行
            hcPortCmdHandleDao.setSlagMoveDist(port, finalId, "110C", distance);
            hcPortCmdHandleDao.writeSlag06(port, finalId, "110E", speed);

            //电机使能 01
            hcPortCmdHandleDao.motorWriteSlagReady(port, finalId);

            DelayUtil.delayedExecution(500, () -> {
                //开始的时候，先让 Z || P 轴 继电器断开 io->01 写入 00
                ioHandleDao.ioWriteCoilSignal(ioAddress, "FF00", new CommonCallback<byte[]>() {
                    @Override
                    public void statusCallback(byte[] bytes) {

                    }
                });
                //运动使能 17
                DelayUtil.delayedExecution(500, () ->
                        hcPortCmdHandleDao.motorWriteSlagRun(port, finalId));
            });
        });

        return WebResult.okResult("Motor read success!");
    }

    /*
        除渣 Z && P轴停止
    */
    @GetMapping("/slagStopZP")
    public WebResult<String> slagStopZP(String id, int ioAddress) {
        String port = getPort(id);
        id = getId(id);
        //开始的时候，先让 Z || P 轴 继电器断开 io->01 写入 00
        ioHandleDao.ioWriteCoilSignal(ioAddress, "0000", new CommonCallback<byte[]>() {
            @Override
            public void statusCallback(byte[] bytes) {

            }
        });

        String finalId = id;
        DelayUtil.delayedExecution(500, () ->
                //其次让电机停止使能 00
                hcPortCmdHandleDao.motorWriteSlagStop(port, finalId));

        return WebResult.okResult("Motor stop success!");
    }

    /*
        控制IO输入
    */
    @GetMapping("/slagSetCoil")
    public WebResult<String> slagSetCoil(int ioAddress, boolean open) {
        ioHandleDao.ioWriteCoilSignal(ioAddress, open ? "FF00" : "0000", new CommonCallback<byte[]>() {
            @Override
            public void statusCallback(byte[] bytes) {

            }
        });
        return WebResult.okResult("Motor:" + ioAddress + "当前状态:" + open + "success!");
    }

    @GetMapping("/slagLiftCage")
    public WebResult<String> slagLiftCage(int id) {

        return WebResult.okResult("Motor:" + "success!");
    }

}
